# -*- coding: utf-8 -*-
# @Time    : 2020/3/5 上午1:10
# @Author  : lilong

from models.state_model.frame_model import Context, State

"""
该v2模式：
    （1）在有些复杂场景下，可以把决定状态变化的属性单独抽象成一个类stateinfo，这样判断状态属性是否符合
        当前的状态ismatch时就可以传入更多的信息。
    （2）每一种状态应当只有唯一的实例
优点：
    （1）封装了状态的准换规则，在状态模式中可以将状态的转换代码封装在环境类中，对状态准换代码进行集中管理，
        而不是分散在各个业务逻辑中。
    （2）将所有与某个状态有关的行为放到一个类中（状态类），使开发人员只关注于该状态下的逻辑开发。
    （3）允许状态准换逻辑与状态对象合为一体，使用时只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
缺点：
    （1）增加系统类和对象的个数。
    （2）状态模式的结构和实现比较复杂，如果使用不当，容易导致程序结构和代码混乱。


应用场景：
    （1）一个对象的行为取决于它的状态，并且它在运行时可能经常改变它的状态，从而改变它的行为。
    （2）一个操作中含有庞大的多分支的条件语句，这些分支依赖于对象的状态，并且每一个分支逻辑复杂，我们可以使用
        模式来拆分不同的分支逻辑，使程序有更好的可读性和可维护性。
"""


class Water(Context):
    """水(H2O)"""

    def __init__(self):
        super().__init__()
        self.addState(SolidState("固态"))
        self.addState(LiquidState("液态"))
        self.addState(GaseousState("气态"))
        self.setTemperature(25)

    def getTemperature(self):
        return self._getStateInfo()

    def setTemperature(self, temperature):
        self._setStateInfo(temperature)

    def riseTemperature(self, step):
        self.setTemperature(self.getTemperature() + step)

    def reduceTemperature(self, step):
        self.setTemperature(self.getTemperature() - step)

    def behavior(self):
        state = self.getState()
        if(isinstance(state, State)):
            state.behavior(self)    # self是作为一个参数传入


# 单例的装饰器
def singleton(cls, *args, **kwargs):
    """构造一个单例的装饰器"""

    instance = {}

    def __singleton(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]

    return __singleton


@singleton
class SolidState(State):
    """固态"""

    def __init__(self, name):
        super().__init__(name)

    def isMatch(self, stateInfo):
        return stateInfo < 0

    def behavior(self, context):
        print("我性格高冷，当前体温", context._getStateInfo(),
              "℃，我坚如钢铁，仿如一冷血动物，请用我砸人，嘿嘿……")


@singleton
class LiquidState(State):
    """液态"""

    def __init__(self, name):
        super().__init__(name)

    def isMatch(self, stateInfo):
        return (stateInfo >= 0 and stateInfo < 100)

    def behavior(self, context):
        print("我性格温和，当前体温", context._getStateInfo(),
              "℃，我可滋润万物，饮用我可让你活力倍增……")


@singleton
class GaseousState(State):
    """气态"""

    def __init__(self, name):
        super().__init__(name)

    def isMatch(self, stateInfo):
        return stateInfo >= 100

    def behavior(self, context):
        print("我性格热烈，当前体温", context._getStateInfo(),
              "℃，飞向天空是我毕生的梦想，在这你将看不到我的存在，我将达到无我的境界……")


def testState():
    water = Water()
    water.behavior()
    water.setTemperature(-4)
    water.behavior()
    water.riseTemperature(18)
    water.behavior()
    water.riseTemperature(110)
    water.behavior()


testState()
